package org.hxyjs.shiro.Realm;
import org.hxyjs.entity.Account;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.util.ByteSource;
import org.hxyjs.entity.AccountRole;
import org.hxyjs.entity.Permission;
import org.hxyjs.service.AccountService;
import org.hxyjs.utils.ContextUtils;

import java.sql.SQLException;
import java.util.HashSet;
import java.util.List;
import java.util.Optional;
import java.util.Set;

/**
 * 编写自定义Realm
 *
 * @author
 *
 */
public class CustomRealm extends AuthorizingRealm {

	/** 用户的业务类 **/
	private AccountService accountService;


	public AccountService getAccountService() {
		return accountService;
	}

	public void setAccountService(AccountService accountService) {
		this.accountService = accountService;
	}

	@Override
	protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
		// TODO Auto-generated method stub
		String username = (String) token.getPrincipal();
		Subject subject = SecurityUtils.getSubject();//subject是单例 所以通过工具类获得是同一个
		String modelName = subject.getSession().getAttribute("modelName").toString();//从session 也是同一个（shiro包装了基本的httpSession 浏览器不换就是同一个）
		System.out.println(modelName+"   oooooooooooooooooooooooooooooooo");
	    String[] names = 	ContextUtils.getSpringMVCContext().getBeanDefinitionNames();

		accountService = (AccountService) ContextUtils.getSpringMVCContext().getBean(modelName+"Service");

		Account account = null;


		try {
			account = accountService.getAccountByAccountName(username).getT();
		} catch (SQLException e) {
			e.printStackTrace();
		} catch (Exception e) {
			e.printStackTrace();
		}
		if (account == null) {

			// 抛出 帐号找不到异常
			throw new UnknownAccountException();
		} else {
			System.out.println("账号密码盐检查点");
			 System.out.println(username+" "+ account.getPassword() +" "+
			 account.getCredentialsSalt());

		}
		// 判断帐号是否锁定
		if (Boolean.TRUE.equals(account.getLocked())) {
			// 抛出 帐号锁定异常
			throw new LockedAccountException();
		}

		// 交给AuthenticatingRealm使用CredentialsMatcher进行密码匹配
		SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(account.getAccountname(), // 用户名
				account.getPassword(), // 密码
				ByteSource.Util.bytes(account.getCredentialsSalt()), // salt=username+salt
				getName() // realm name
		);
		subject.getSession().setAttribute("user", account);
		return authenticationInfo;
	}

	@Override
	protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
		// 获取当前用户，用户在登录时候提供了用户名明码形成 用户密码token（令牌），令牌中又可以生成
        //负责人Principal，所以找到负责人就可以拿到用户名
		System.out.println("111aaaaaaaaaaa");
		String accountName = (String) principalCollection.getPrimaryPrincipal();
		Subject subject = SecurityUtils.getSubject();//subject是单例 所以通过工具类获得是同一个
		String modelName = subject.getSession().getAttribute("modelName").toString();//从session 也是同一个（shiro包装了基本的httpSession 浏览器不换就是同一个）
		System.out.println(modelName+"   oooooooooooooooooooooooooooooooo11");
		AccountService accountService = (AccountService) ContextUtils.getSpringMVCContext().getBean(modelName+"Service");
		System.out.println(accountName+"      6666666KKK");
		Account account = null;
		try {
			account = (Account) accountService.getAccountByAccountName(accountName).getT();
			System.out.println(account+" 5435434");
			subject.getSession().setAttribute("user", account);
		} catch (SQLException e) {
			e.printStackTrace();
		} catch (Exception e) {
			e.printStackTrace();
		}
		// 内置用户:授予所有权限
		List<Permission> permissions = null;
		// if (user != null && user.getUsername().equals("admin")) {
		// permissions = permissionDao.findAll();
		// } else { // 其他普通用户:查出该用户对应的所有权限

		// }

		// 授权
		SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
		Set<String> roles = new HashSet<String>();
		System.out.println("权限对象检查点");
		System.out.println("账号是否为null "+account+" "+  account.getAccountRoles());
		if (!Optional.ofNullable(account.getAccountRoles()).isPresent()){
			return info;
		}
		for (AccountRole accountRole : account.getAccountRoles()) {
			System.out.println("------ 当前用户有的角色--------");
			System.out.println(accountRole.getRole().getName());
			roles.add(accountRole.getRole().getName());
			for (Permission p : accountRole.getRole().getPermissions()) {
				System.out.println("------ 当前用户有的权限--------");
				System.out.println(p.getDescription());
				info.addStringPermission(p.getDescription());
			}
		}
		info.setRoles(roles);
		return info;
	}

	@Override
	public void clearCachedAuthorizationInfo(PrincipalCollection principals) {
		super.clearCachedAuthorizationInfo(principals);
	}

	@Override
	public void clearCachedAuthenticationInfo(PrincipalCollection principals) {
		super.clearCachedAuthenticationInfo(principals);
	}

	@Override
	public void clearCache(PrincipalCollection principals) {
		super.clearCache(principals);
	}

	public void clearAllCachedAuthorizationInfo() {
		getAuthorizationCache().clear();
	}

	public void clearAllCachedAuthenticationInfo() {
		getAuthenticationCache().clear();
	}

	public void clearAllCache() {
		clearAllCachedAuthenticationInfo();
		clearAllCachedAuthorizationInfo();
	}

	// /***
	// * 获取授权信息
	// */
	// //根据自己系统规则的需要编写获取授权信息，这里为了快速入门只获取了用户对应角色的资源url信息
	// @Override
	// protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection
	// pc) {
	// String accountname = (String)pc.fromRealm(getName()).iterator().next();
	// if(accountname!=null){
	// List<String> pers =
	// studentService.getPermissionsByStudentName(accountname);
	// if(pers!=null && !pers.isEmpty()){
	// SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
	// for(String each:pers){
	// //将权限资源添加到用户信息中
	// info.addStringPermission(each);
	// }
	// }
	// }
	// return null;
	// }
	// /***
	// * 获取认证信息
	// */
	// @Override
	// protected AuthenticationInfo doGetAuthenticationInfo(
	// AuthenticationToken at) throws AuthenticationException {
	//
	//
	// UsernamePasswordToken token = (UsernamePasswordToken) at;
	// // 通过表单接收的用户名
	// String accountname = token.getUsername();
	// if(accountname!=null && !"".equals(accountname)){
	// Account account = studentService.getStudentByName(accountname);
	// if (account != null) {
	// return new SimpleAuthenticationInfo(account.getAccountname(),
	// account.getPassword(), getName());
	// }
	// }
	// return null;
	// }

}